﻿using System.IO;
using System;

namespace XmlSockets.Internal
{
    /// <summary>
    /// 
    /// </summary>
    /// <param name="buffer"></param>
    /// <param name="length"></param>
    /// <returns></returns>
    internal delegate IXmlSocketSendContent CreateXmlSocketSendContentHandler(byte[] buffer, long length);

    internal sealed class XmlMessageWriteBufferdStream:Stream
    {



        private byte[] buffer;

        public int SendBufferSize { get; set; }

        private long _postion;

        internal XmlMessageWriteBufferdStream(int size)
        {
            if (size < 0) throw new ArgumentException();
            SendBufferSize = size;
            buffer = new byte[SendBufferSize];

        }


        public override void Flush()
        {

            if (this.Position == 0) throw new InvalidOperationException("バッファにデータが書き込まれていません");
            if(buffer[this.Position -1] != XmlSocketConstant.Boundary_Byte)base.WriteByte(XmlSocketConstant.Boundary_Byte);
            
        }

        public IXmlSocketSendContent CreateContent(CreateXmlSocketSendContentHandler handler)
        {
            try
            {
                if (this.Position == 0) throw new InvalidOperationException("バッファにデータが書き込まれていません");
                if ((buffer[this.Position - 1] != XmlSocketConstant.Boundary_Byte))throw new InvalidOperationException("区切り文字であるNull文字が末尾に存在しません");
                return handler( this.buffer, this.Position);
            }
            finally
            {
                this.Clear();
            }
            
        }



        public void Clear()
        {
            Position = 0;
            SetLength(0);
            Array.Clear(this.buffer, 0, this.buffer.Length);

        }

        

        public override bool CanRead
        {
            get { return true; }
        }

        public override bool CanSeek
        {
            get { return true; }
        }

        public override bool CanWrite
        {
            get { return true; }
        }

        public override long Length
        {
            get { return buffer.Length; }
        }

        public override int Read(byte[] buffer, int offset, int count)
        {
            throw new System.NotImplementedException();
        }

        public override long Seek(long offset, SeekOrigin origin)
        {
            switch (origin)
            {
                case SeekOrigin.Begin:
                    Position = offset;
                    break;

                case SeekOrigin.Current:
                    Position += offset;
                    break;

                case SeekOrigin.End:
                    Position = Length + offset;
                    break;

                default:
                    throw new ArgumentOutOfRangeException();
            }
            return Position;
        }

        public override void SetLength(long value)
        {
            if(value > Length){
                byte[] tmpBuffer =   new byte[value];
                Array.ConstrainedCopy(this.buffer, 0, tmpBuffer, 0, (int)this.buffer.Length);
                this.buffer = tmpBuffer;
            }

        }

        public override void Write(byte[] buffer, int offset, int count)
        {
            while (count >= (Length - Position)) ExtendBuffer();
            Array.ConstrainedCopy(buffer, offset, this.buffer, (int)Position, count);
            Position += count;

        }

        public override void WriteByte(byte value)
        {
            if (Position >= Length) ExtendBuffer();
            this.buffer[Position] = value;
            Position++;
        }

        private void ExtendBuffer()
        {
            this.SetLength((Length * 2) +1);
        }

        public override long Position
        {
            get
            {
                return _postion;
            }
            set
            {
                _postion = value;
            }
        }
    }
}
